(* test/test_semantic.ml *)
open Toyc.Ast
open Toyc.Semantic

(* 辅助函数：打印语义分析结果 *)
let print_semantic_result result =
  let print_func_info name info =
    Printf.printf "Function: %s\n" name;
    Printf.printf "  Return type: %s\n" 
      (match info.return_type with Int -> "int" | Void -> "void");
    Printf.printf "  Parameters: ";
    List.iter (fun (t, n) -> 
      Printf.printf "%s %s, " (match t with Int -> "int" | Void -> "void") n
    ) info.params;
    print_endline "\n"
  in
  
  StringMap.iter print_func_info result.funcs;
  print_endline "Semantic analysis completed successfully!"

(* 测试用例定义 *)
let test_cases = [
  (* 有效程序：只有main函数 *)
  ( "Valid main function",
    [{
      return_type = Int;
      name = "main";
      params = [];
      body = [Return (Some (Number 0))]
    }]
  );
  
  (* 无效：缺少main函数 *)
  ( "Missing main function",
    [{
      return_type = Int;
      name = "foo";
      params = [];
      body = [Return (Some (Number 0))]
    }]
  );
  
  (* 无效：main函数有参数 *)
  ( "Main with parameters",
    [{
      return_type = Int;
      name = "main";
      params = [(Int, "arg")];
      body = [Return (Some (Number 0))]
    }]
  );
  
  (* 无效：main函数返回void *)
  ( "Main returns void",
    [{
      return_type = Void;
      name = "main";
      params = [];
      body = []
    }]
  );
  
  (* 无效：重复函数声明 *)
  ( "Duplicate functions",
    [
      {
        return_type = Int;
        name = "foo";
        params = [];
        body = [Return (Some (Number 0))]
      };
      {
        return_type = Void;
        name = "foo";
        params = [];
        body = []
      }
    ]
  );
  
  (* 有效：变量作用域 - 嵌套作用域 *)
  ( "Variable scoping - nested blocks",
    [{
      return_type = Int;
      name = "main";
      params = [];
      body = [
        Block [
          VarDecl ("x", Number 1); (* 外层x *)
          Block [
            VarDecl ("x", Number 2); (* 内层x - 允许 *)
            ExprStmt (Identifier "x") (* 使用内层x *)
          ];
          ExprStmt (Identifier "x") (* 使用外层x *)
        ];
        Return (Some (Number 0))
      ]
    }]
  );
  
  (* 无效：同一作用域重复声明变量 *)
  ( "Duplicate variable in same scope",
    [{
      return_type = Int;
      name = "main";
      params = [];
      body = [
        VarDecl ("x", Number 1);
        VarDecl ("x", Number 2); (* 重复声明 *)
        Return (Some (Number 0))
      ]
    }]
  );
  
  (* 无效：未定义变量 *)
  ( "Undefined variable",
    [{
      return_type = Int;
      name = "main";
      params = [];
      body = [
        ExprStmt (Identifier "x"); (* 未定义 *)
        Return (Some (Number 0))
      ]
    }]
  );
  
  (* 无效：返回类型不匹配 - int函数无返回值 *)
  ( "Int function missing return",
    [{
      return_type = Int;
      name = "main";
      params = [];
      body = [] (* 缺少return *)
    }]
  );
  
  (* 无效：返回类型不匹配 - void函数有返回值 *)
  ( "Void function with return value",
    [{
      return_type = Void;
      name = "foo";
      params = [];
      body = [Return (Some (Number 0))]
    }]
  );
  
  (* 有效：void函数无返回值 *)
  ( "Valid void function without return",
    [{
      return_type = Void;
      name = "foo";
      params = [];
      body = []
    }]
  );
  
  (* 无效：循环外使用break *)
  ( "Break outside loop",
    [{
      return_type = Int;
      name = "main";
      params = [];
      body = [
        Break; (* 不在循环内 *)
        Return (Some (Number 0))
      ]
    }]
  );
  
  (* 无效：循环外使用continue *)
  ( "Continue outside loop",
    [{
      return_type = Int;
      name = "main";
      params = [];
      body = [
        Continue; (* 不在循环内 *)
        Return (Some (Number 0))
      ]
    }]
  );
  
  (* 有效：函数调用 *)
  ( "Function call",
    [
      {
        return_type = Int;
        name = "foo";
        params = [(Int, "x")];
        body = [Return (Some (Identifier "x"))]
      };
      {
        return_type = Int;
        name = "main";
        params = [];
        body = [
          ExprStmt (Call ("foo", [Number 42]));
          Return (Some (Number 0))
        ]
      }
    ]
  );
  
  (* 无效：参数数量错误 *)
  ( "Incorrect argument count",
    [
      {
        return_type = Int;
        name = "foo";
        params = [(Int, "x"); (Int, "y")];
        body = [Return (Some (BinaryOp (Add, Identifier "x", Identifier "y")))]
      };
      {
        return_type = Int;
        name = "main";
        params = [];
        body = [
          ExprStmt (Call ("foo", [Number 42])); (* 缺少一个参数 *)
          Return (Some (Number 0))
        ]
      }
    ]
  );
  
  (* 无效：参数类型不匹配 *)
  ( "Argument type mismatch",
    [
      {
        return_type = Void;
        name = "foo";
        params = [];
        body = []
      };
      {
        return_type = Int;
        name = "main";
        params = [];
        body = [
          (* 尝试将void函数结果作为参数传递 *)
          ExprStmt (Call ("bar", [Call ("foo", [])]));
          Return (Some (Number 0))
        ]
      }
    ]
  );
  
  (* 无效：条件表达式类型错误 *)
  ( "Invalid condition type",
    [
      {
        return_type = Void;
        name = "foo";
        params = [];
        body = []
      };
      {
        return_type = Int;
        name = "main";
        params = [];
        body = [
          If (Call ("foo", []), (* 条件应为整数 *)
            Block [Return (Some (Number 0))],
            None
          )
        ]
      }
    ]
  );
  
  (* 有效：复杂作用域嵌套 *)
  ( "Complex scoping with loops and conditionals",
    [{
      return_type = Int;
      name = "main";
      params = [];
      body = [
        VarDecl ("a", Number 1);
        While (Identifier "a", Block [
          VarDecl ("b", Number 2);
          If (Identifier "a", Block [
            VarDecl ("c", Number 3);
            ExprStmt (BinaryOp (Assign, Identifier "a", Number 0))
          ], None);
          (* 这里c已不可见 *)
        ]);
        Return (Some (Identifier "a"))
      ]
    }]
  );
  
  (* 无效：访问内部作用域变量 *)
  ( "Access inner scope variable",
    [{
      return_type = Int;
      name = "main";
      params = [];
      body = [
        Block [
          VarDecl ("x", Number 1)
        ];
        ExprStmt (Identifier "x"); (* x已超出作用域 *)
        Return (Some (Number 0))
      ]
    }]
  );
  
  (* 有效：函数内嵌套作用域 *)
  ( "Function with nested scopes",
    [
      {
        return_type = Int;
        name = "func";
        params = [(Int, "param")];
        body = [
          VarDecl ("local", Number 10);
          Block [
            VarDecl ("inner", Number 20);
            Return (Some (BinaryOp (Add, Identifier "local", Identifier "inner")))
          ]
        ]
      };
      {
        return_type = Int;
        name = "main";
        params = [];
        body = [
          ExprStmt (Call ("func", [Number 5]));
          Return (Some (Number 0))
        ]
      }
    ]
  );
  
  (* 无效：函数内缺少返回语句 *)
  ( "Function missing return in some paths",
    [{
      return_type = Int;
      name = "main";
      params = [];
      body = [
        If (Number 1,
          Block [Return (Some (Number 1))],
          Some (Block []) (* 缺少返回语句 *)
        )
      ]
    }]
  );
  
  (* 有效：void函数提前返回 *)
  ( "Void function with early return",
    [{
      return_type = Void;
      name = "early_return";
      params = [];
      body = [
        If (Number 1,
          Block [Return None],
          None
        );
        (* 不会执行到这里 *)
        ExprStmt (Call ("some_func", []))
      ]
    }]
  );
  
  (* 无效：赋值给未声明变量 *)
  ( "Assignment to undeclared variable",
    [{
      return_type = Int;
      name = "main";
      params = [];
      body = [
        ExprStmt (BinaryOp (Assign, Identifier "x", Number 5)); 
        Return (Some (Number 0))
      ]
    }]
  );
]

(* 运行所有测试用例 *)
let run_tests () =
  List.iter (fun (name, program) ->
    print_endline ("\n=== Testing: " ^ name ^ " ===");
    try
      let result = check_program program in
      print_semantic_result result;
      print_endline "PASSED"
    with
    | Semantic_error msg -> 
        Printf.printf "Semantic error: %s\n" msg;
        print_endline "FAILED (expected error)"
    | exn -> 
        Printf.printf "Unexpected error: %s\n" (Printexc.to_string exn);
        print_endline "FAILED"
  ) test_cases

(* 主函数 *)
let () =
  print_endline "Starting semantic analysis tests...";
  run_tests ();
  print_endline "\nAll tests completed!"